home *** CD-ROM | disk | FTP | other *** search
- #define VERSION "1.14 01-15-87"
- #define PUBDIR "/usr/spool/uucppublic"
-
- /*% cc -DNFGVMIN -DCRCTABLE -K -O -i % -o rz; size rz
- *
- * rz.c By Chuck Forsberg
- * MS-DOS version by Francois Bergeon
- *
- * cc -O rz.c -o rz USG (3.0) Unix
- * cc -O -DV7 rz.c -o rz Unix V7, BSD 2.8 - 4.3
- * cl rz.c -link stty MS-DOS, MS-C 4.00+
- *
- * ln rz rb For USG or V7
- *
- * ln rz /usr/bin/rzrmail For remote mail. Make this the
- * login shell. rzrmail then calls
- * rmail(1) to deliver mail.
- *
- * define CRCTABLE to use table driven CRC
- *
- * Unix is a trademark of Western Electric Company
- *
- * A program for Unix to receive files and commands from computers running
- * Professional-YAM, PowerCom, YAM, IMP, or programs supporting XMODEM.
- * rz uses Unix buffered input to reduce wasted CPU time.
- *
- * Iff the program is invoked by rzCOMMAND, output is piped to
- * "COMMAND filename"
- *
- * Some systems (Venix, Coherent, Regulus) may not support tty raw mode
- * read(2) the same way as Unix. ONEREAD must be defined to force one
- * character reads for these systems. Added 7-01-84 CAF
- *
- * Alarm signal handling changed to work with 4.2 BSD 7-15-84 CAF
- *
- * NFGVMIN Added 1-13-85 CAF for PC-AT Xenix systems where c_cc[VMIN]
- * doesn't seem to work (even though it compiles without error!).
- *
- * HOWMANY should be tuned for best performance
- *
- * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
- *
- * MS-DOS Adaptation 10-19-87 for the MS-C compiler rev 4.00+
- * using Francois Bergeon's tty library
- */
- #define LOGFILE "/tmp/rzlog"
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
-
- #ifdef MSDOS
- #include <time.h>
- #define CRCTABLE
- #define JAN1ST70 315532800
- #else
- FILE *popen();
- #endif
-
- #define OK 0
- #define FALSE 0
- #define TRUE 1
- #define ERROR (-1)
-
- /*
- * Max value for HOWMANY is 255.
- * A larger value reduces system overhead but may evoke kernel bugs.
- * 133 corresponds to a XMODEM/CRC sector
- */
- #ifndef HOWMANY
- #define HOWMANY 133
- #endif
-
- int Zmodem = 0; /* ZMODEM protocol requested */
- int Nozmodem = 0; /* If invoked as "rb" */
- unsigned Baudrate;
- #include "rbsb.c" /* most of the system dependent stuff here */
-
- char *substr();
- FILE *fout;
-
- /*
- * Routine to calculate the free bytes on the current file system
- * ~0 means many free bytes (unknown)
- */
- long getfree()
- {
- return(~0L); /* many free bytes ... */
- }
-
- /* Ward Christensen / CP/M parameters - Don't change these! */
- #define ENQ 005
- #define CAN ('X'&037)
- #define XOFF ('s'&037)
- #define XON ('q'&037)
- #define SOH 1
- #define STX 2
- #define EOT 4
- #define ACK 6
- #define NAK 025
- #define CPMEOF 032
- #define WANTCRC 'C' /* send C not NAK to get crc not checksum */
- #define TIMEOUT (-2)
- #define RCDO (-3)
- #define ERRORMAX 5
- #define RETRYMAX 5
- #define WCEOT (-10)
- #define SECSIZ 128 /* cp/m's Magic Number record size */
- #define PATHLEN 257 /* ready for 4.2 bsd ? */
- #define KSIZE 1024 /* record size with k option */
- #define UNIXFILE 0x8000 /* happens to the the S_IFREG file mask bit for stat */
-
- int Lastrx;
- int Crcflg = FALSE;
- int Firstsec;
- int Eofseen; /* indicates cpm eof (^Z) has been received */
- int errors;
- int Restricted = 0; /* restricted; no /.. or ../ in filenames */
- #ifdef ONEREAD /* Sorry, Regulus and some others don't */
- int Readnum = 1; /* work right in raw mode! */
- #else
- int Readnum = HOWMANY; /* Number of bytes to ask for in read() from modem */
- #endif
-
- #define DEFBYTL 2000000000L /* default rx file size */
- long Bytesleft; /* number of bytes of incoming file left */
- long Modtime; /* Unix style mod time for incoming file */
- short Filemode; /* Unix style mode for incoming file */
- char Pathname[PATHLEN];
- char *Progname; /* the name by which we were called */
-
- int Batch = 0;
- int Wcsmask = 0377;
- int Topipe = 0;
- int MakeLCPathname = TRUE; /* make received pathname lower case */
- int Verbose = 0;
- int Quiet = 0; /* overrides logic that would otherwise set verbose */
- int Nflag = 0; /* Don't really transfer files */
- int Rxbinary = FALSE; /* receive all files in bin mode */
- int Rxascii = FALSE; /* receive files in ascii (translate) mode */
- int Thisbinary; /* current file is to be received in bin mode */
- int Blklen; /* record length of received packets */
- char secbuf[KSIZE];
- char linbuf[HOWMANY];
- int Lleft = 0; /* number of characters in linbuf */
- time_t timep[2];
- char Lzmanag; /* Local file management request */
- char zconv; /* ZMODEM file conversion request */
- char zmanag; /* ZMODEM file management request */
- char ztrans; /* ZMODEM file transport request */
-
- jmp_buf tohere; /* For the interrupt on RX timeout */
-
- #include "zm.c"
-
- int tryzhdrtype = ZRINIT; /* Header type to send corresponding to */
- /* Last rx close */
-
- alrm()
- {
- longjmp(tohere, -1);
- }
-
- /* called by signal interrupt or terminate to clean things up */
- bibi(n)
- {
- if (Zmodem)
- zmputs(Attn);
- canit();
- mode(0);
- fprintf(stderr, "rz: caught signal %d; exiting\n", n);
- exit(128+n);
- }
-
- main(argc, argv)
- char *argv[];
- {
- char *cp;
- register npats;
- char *virgin, **patts;
- char *getenv();
- int exitcode;
-
- Rxtimeout = 100;
- setbuf(stderr, NULL);
- if ((cp = getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
- Restricted = TRUE;
-
- #ifndef MSDOS
- chkinvok((virgin = argv[0])); /* if called as [-]rzCOMMAND set flag */
- #else
- Progname = virgin = "rz";
- #endif
- npats = 0;
- while (--argc)
- {
- cp = *++argv;
- if (*cp++ == '-' && *cp)
- {
- while (*cp)
- {
- switch (*cp++)
- {
- case '+':
- Lzmanag = ZMAPND;
- break;
- #ifndef MSDOS
- case '1':
- iofd = 1;
- break;
- #else
- case '2':
- port = "COM2";
- break;
- case 's':
- Baudrate = atoi(cp);
- if ((speed = getspeed(Baudrate)) < 0)
- usage();
- *cp = '\0';
- break;
- case 'Y':
- Nozmodem = TRUE;
- break;
- #endif
- case '7':
- Wcsmask = 0177;
- case 'a':
- Rxascii = TRUE;
- break;
- case 'b':
- Rxbinary = TRUE;
- break;
- case 'c':
- Crcflg = TRUE;
- break;
- case 'D':
- Nflag = TRUE;
- break;
- case 'p':
- Lzmanag = ZMPROT;
- break;
- case 'q':
- Quiet = TRUE;
- Verbose = 0;
- break;
- case 't':
- if (--argc < 1)
- usage();
- Rxtimeout = atoi(*++argv);
- if (Rxtimeout < 10 || Rxtimeout > 1000)
- usage();
- break;
- case 'u':
- MakeLCPathname = FALSE;
- break;
- case 'v':
- ++Verbose;
- break;
- default:
- usage();
- }
- }
- }
- else if (!npats && argc > 0)
- {
- if (argv[0][0])
- {
- npats = argc;
- patts = argv;
- #ifdef MSDOS
- if (!strcmp(*patts, "-"))
- Topipe = TRUE;
- #endif
- }
- }
- }
- if (npats > 1)
- usage();
- if (Verbose)
- {
- if (freopen(LOGFILE, "a", stderr) == NULL)
- {
- printf("Can't open log file %s\n",LOGFILE);
- exit(0200);
- }
- setbuf(stderr, NULL);
- fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
- }
- if (fromcu() && !Quiet)
- if (!Verbose)
- Verbose = 2;
-
- mode(1);
-
- if (signal(SIGINT, bibi) == SIG_IGN)
- {
- signal(SIGINT, SIG_IGN);
- #ifndef MSDOS
- signal(SIGKILL, SIG_IGN);
- #endif
- }
- else
- {
- signal(SIGINT, bibi);
- #ifndef MSDOS
- signal(SIGKILL, bibi);
- #endif
- }
- if (wcreceive(npats, patts) == ERROR)
- {
- exitcode=0200;
- canit();
- }
- mode(0);
- if (exitcode && !Zmodem) /* bellow again with all thy might. */
- canit();
- exit(exitcode);
- }
-
-
- usage()
- {
- fprintf(stderr,"%s %s for %s by Chuck Forsberg\n", Progname, VERSION, OS);
- #ifndef MSDOS
- fprintf(stderr,"Usage: rz [-1abuv] (ZMODEM Batch)\n");
- fprintf(stderr,"or rb [-1abuv] (YMODEM Batch)\n");
- fprintf(stderr,"or rz [-1abcv] file (XMODEM or XMODEM-1k)\n");
- fprintf(stderr," -1 For cu(1): Use fd 1 for input\n");
- #else
- fprintf(stderr,"Usage: rz [-2abuv] [-s<speed>] [-] (ZMODEM Batch)\n");
- fprintf(stderr,"or rz [-2abuv] [-s<speed>] [-] -Y (YMODEM Batch)\n");
- fprintf(stderr,"or rz [-2abcv] [-s<speed>] file (XMODEM)\n");
- fprintf(stderr," -2 Use COM2 instead of COM1\n");
- fprintf(stderr," - Pipe output to stdout\n");
- #endif
- fprintf(stderr," -a ASCII transfer (strip CR)\n");
- fprintf(stderr," -b Binary transfer for all files\n");
- fprintf(stderr," -v Verbose more v's give more info\n");
- fprintf(stderr," -c Use 16 bit CRC (XMODEM)\n");
- exit(1);
- }
- /*
- * Debugging information output interface routine
- */
- /* VARARGS1 */
- vfile(f, a, b, c)
- char *f;
- {
- if (Verbose > 2)
- {
- fprintf(stderr, f, a, b, c);
- fprintf(stderr, "\n");
- }
- }
-
- zperr(f, a, b, c)
- char *f;
- {
- if (Verbose > 1)
- {
- fprintf(stderr, f, a, b, c);
- fprintf(stderr, "\n");
- }
- }
-
- /*
- * Let's receive something already.
- */
-
- char *rbmsg =
- "%s ready. To begin transfer, type \"%s file ...\" to your modem program\r\n";
-
- wcreceive(argc, argp)
- char **argp;
- {
- int c;
-
- if (Batch || argc == 0)
- {
- Crcflg = (Wcsmask == 0377);
- if (!Quiet)
- fprintf(stderr, rbmsg, Progname, Nozmodem ? "sb" : "sz");
- if (c = tryz())
- {
- if (c == ZCOMPL)
- return(OK);
- if (c == ERROR)
- goto fubar;
- c = rzfiles();
- if (c)
- goto fubar;
- }
- else
- {
- for (;;)
- {
- if (wcrxpn(secbuf) == ERROR)
- goto fubar;
- if (secbuf[0] == 0)
- return(OK);
- if (procheader(secbuf) == ERROR)
- goto fubar;
- if (wcrx() == ERROR)
- goto fubar;
- }
- }
- }
- else
- {
- Bytesleft = DEFBYTL;
- Filemode = 0;
- Modtime = 0L;
-
- strcpy(Pathname, *argp);
- checkpath(Pathname);
- fprintf(stderr, "\nrz: ready to receive %s\r\n", Pathname);
- #ifndef MSDOS
- if ((fout = fopen(Pathname, "w")) == NULL)
- #else
- if ((fout = fopen(Pathname, "wb")) == NULL)
- #endif
- return(ERROR);
- Thisbinary = Rxbinary || !Rxascii;
- if (wcrx() == ERROR)
- goto fubar;
- }
- return(OK);
- fubar:
- canit();
- if (Topipe && fout)
- {
- #ifndef MSDOS
- pclose(fout);
- #endif
- return(ERROR);
- }
- if (fout)
- fclose(fout);
- if (Restricted)
- {
- unlink(Pathname);
- fprintf(stderr, "\r\nrz: %s removed.\r\n", Pathname);
- }
- return(ERROR);
- }
-
-
- /*
- * Fetch a pathname from the other end as a C ctyle ASCIZ string.
- * Length is indeterminate as long as less than Blklen
- * A null string represents no more files (YMODEM)
- */
- wcrxpn(rpn)
- char *rpn; /* receive a pathname */
- {
- register c;
-
- #ifdef NFGVMIN
- readline(1);
- #else
- purgeline();
- #endif
-
- et_tu:
- Firstsec = TRUE;
- Eofseen = FALSE;
- sendline(Crcflg ? WANTCRC : NAK);
- Lleft = 0; /* Do read next time ... */
- while ((c = wcgetsec(rpn, 100)) != 0)
- {
- log("Pathname fetch returned %d\n", c);
- if (c == WCEOT)
- {
- sendline(ACK);
- Lleft = 0; /* Do read next time ... */
- readline(1);
- goto et_tu;
- }
- return(ERROR);
- }
- sendline(ACK);
- return(OK);
- }
-
- /*
- * Adapted from CMODEM13.C, written by
- * Jack M. Wierda and Roderick W. Hart
- */
-
- wcrx()
- {
- register int sectnum, sectcurr;
- register char sendchar;
- register char *p;
- int cblklen; /* bytes to dump this block */
-
- Firstsec = TRUE;
- sectnum = 0;
- Eofseen = FALSE;
- sendchar = (Crcflg ? WANTCRC : NAK);
- for (;;)
- {
- sendline(sendchar); /* send it now, we're ready! */
- Lleft = 0; /* Do read next time ... */
- sectcurr = wcgetsec(secbuf, 100);
- report(sectcurr);
- if (sectcurr == (sectnum+1 & Wcsmask))
- {
- sectnum++;
- cblklen = ((Bytesleft > Blklen) ? Blklen : Bytesleft);
- if (putsec(secbuf, cblklen) == ERROR)
- return(ERROR);
- if ((Bytesleft -= cblklen) < 0)
- Bytesleft = 0;
- sendchar = ACK;
- }
- else if (sectcurr == (sectnum & Wcsmask))
- {
- log("Received dup Sector\n");
- sendchar = ACK;
- }
- else if (sectcurr == WCEOT)
- {
- if (closeit())
- return(ERROR);
- sendline(ACK);
- Lleft = 0; /* Do read next time ... */
- return(OK);
- }
- else if (sectcurr == ERROR)
- return(ERROR);
- else
- {
- log("Sync Error\n");
- return(ERROR);
- }
- }
- }
-
- /*
- * Wcgetsec fetches a Ward Christensen type sector.
- * Returns sector number encountered or ERROR if valid sector not received,
- * or CAN CAN received
- * or WCEOT if eot sector
- * time is timeout for first char, set to 4 seconds thereafter
- ***************** NO ACK IS SENT IF SECTOR IS RECEIVED OK **************
- * (Caller must do that when he is good and ready to get next sector)
- */
-
- wcgetsec(rxbuf, maxtime)
- char *rxbuf;
- int maxtime;
- {
- int checksum, wcj, firstch;
- unsigned short oldcrc;
- char *p;
- int sectcurr;
-
- for (Lastrx = errors = 0; errors < RETRYMAX; errors++)
- {
-
- if ((firstch = readline(maxtime)) == STX)
- {
- Blklen = KSIZE;
- goto get2;
- }
- if (firstch == SOH)
- {
- Blklen = SECSIZ;
- get2:
- sectcurr = readline(1);
- if ((sectcurr + (oldcrc = readline(1))) == Wcsmask)
- {
- oldcrc = checksum = 0;
- for (p = rxbuf, wcj = Blklen; --wcj >= 0; )
- {
- if ((firstch = readline(1)) < 0)
- goto bilge;
- oldcrc = updcrc(firstch, oldcrc);
- checksum += firstch;
- *p++ = firstch;
- }
- if ((firstch = readline(1)) < 0)
- goto bilge;
- if (Crcflg)
- {
- oldcrc = updcrc(firstch, oldcrc);
- if ((firstch = readline(1)) < 0)
- goto bilge;
- oldcrc = updcrc(firstch, oldcrc);
- if (oldcrc & 0xFFFF)
- log("CRC=0%o\n", oldcrc);
- else
- {
- Firstsec = FALSE;
- return(sectcurr);
- }
- }
- else if (((checksum - firstch) & Wcsmask) == 0)
- {
- Firstsec = FALSE;
- return(sectcurr);
- }
- else
- log("Checksum Error\n");
- }
- else
- log("Sector number garbled 0%o 0%o\n", sectcurr, oldcrc);
- }
- /* make sure eot really is eot and not just mixmash */
- #ifdef NFGVMIN
- else if (firstch == EOT && readline(1) == TIMEOUT)
- return(WCEOT);
- #else
- else if (firstch == EOT && Lleft == 0)
- return(WCEOT);
- #endif
- else if (firstch == CAN)
- {
- if (Lastrx == CAN)
- {
- log("Sender CANcelled\n");
- return(ERROR);
- }
- else
- {
- Lastrx = CAN;
- continue;
- }
- }
- else if (firstch == TIMEOUT)
- {
- if (Firstsec)
- goto humbug;
- bilge:
- log("Timeout\n");
- }
- else
- log("Got 0%o sector header\n", firstch);
-
- humbug:
- Lastrx = 0;
- while (readline(1) != TIMEOUT)
- {;}
- if (Firstsec)
- {
- sendline(Crcflg ? WANTCRC : NAK);
- Lleft = 0; /* Do read next time ... */
- }
- else
- {
- maxtime = 40;
- sendline(NAK);
- Lleft = 0; /* Do read next time ... */
- }
- }
- /* try to stop the bubble machine. */
- canit();
- return(ERROR);
- }
-
- /*
- * This version of readline is reasoably well suited for
- * reading many characters.
- * (except, currently, for the Regulus version!)
- *
- * timeout is in tenths of seconds
- */
- readline(timeout)
- int timeout;
- {
- int n;
- static char *cdq; /* pointer for removing chars from linbuf */
- #ifdef MSDOS
- time_t start;
- #endif
-
- if (--Lleft >= 0)
- {
- if (Verbose > 8)
- fprintf(stderr, "%02x ", *cdq&0377);
- return(*cdq++ & Wcsmask);
- }
- n = timeout/10;
- if (n < 2)
- n = 3;
- if (Verbose > 3)
- fprintf(stderr, "Calling read: n=%d ", n);
- #ifndef MSDOS
- if (setjmp(tohere))
- {
- #ifdef TIOCFLUSH
- /* ioctl(iofd, TIOCFLUSH, 0); */
- #endif
- Lleft = 0;
- if (Verbose > 1)
- fprintf(stderr, "Readline:TIMEOUT\n");
- return(TIMEOUT);
- }
- signal(SIGALRM, alrm);
- alarm(n);
- Lleft = read(iofd, (cdq = linbuf), Readnum);
- alarm(0);
- #else
- time(&start);
- while (!(Lleft = tty_read(iofd, (cdq = linbuf), Readnum)) &&
- (int)difftime(time(NULL), start) < n)
- {;}
- if (!Lleft)
- {
- Lleft = 0;
- if (Verbose > 1)
- fprintf(stderr, "Readline:TIMEOUT\n");
- return(TIMEOUT);
- }
- #endif
-
- if (Verbose > 3)
- fprintf(stderr, "Read returned %d bytes\n", Lleft);
- if (Lleft < 1)
- return(TIMEOUT);
- --Lleft;
- if (Verbose > 8)
- fprintf(stderr, "%02x ", *cdq&0377);
- return(*cdq++ & Wcsmask);
- }
-
-
-
- /*
- * Purge the modem input queue of all characters
- */
- purgeline()
- {
- #ifdef USG
- ioctl(iofd, TCFLSH, 0);
- #endif
- #ifdef V7
- lseek(iofd, 0L, 2);
- #endif
- #ifdef MSDOS
- char c;
-
- while (tty_read(iofd, &c, 1))
- {;}
- #endif
- Lleft = 0;
- }
-
-
- /*
- * Process incoming file information header
- */
- procheader(name)
- char *name;
- {
- char *openmode, *p, **pp;
-
- /* set default parameters and overrides */
- #ifndef MSDOS
- openmode = "w";
- #else
- openmode = "wb";
- #endif
- Thisbinary = Rxbinary || !Rxascii;
- if (Lzmanag)
- zmanag = Lzmanag;
-
- /*
- * Process ZMODEM remote file management requests
- */
- if (!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
- Thisbinary = 0;
- if (zconv == ZCBIN) /* Remote Binary override */
- ++Thisbinary;
- else if (zmanag == ZMAPND)
- #ifndef MSDOS
- openmode = "a";
- #else
- openmode = "ab";
- #endif
- /* ZMPROT check for existing file */
- if (zmanag == ZMPROT && (fout = fopen(name, "r")))
- {
- fclose(fout);
- return(ERROR);
- }
-
- Bytesleft = DEFBYTL;
- Filemode = 0;
- Modtime = 0L;
-
- p = name + 1 + strlen(name);
- if (*p)
- {
- /* file coming from Unix or DOS system */
- sscanf(p, "%ld%lo%o", &Bytesleft, &Modtime, &Filemode);
- if (Filemode & UNIXFILE)
- ++Thisbinary;
- if (Verbose)
- fprintf(stderr, "Incoming: %s %ld %lo %o\n",
- name, Bytesleft, Modtime, Filemode);
- }
- else
- {
- /* File coming from CP/M system */
- for (p = name; *p; ++p) /* change / to _ */
- if (*p == '/')
- *p = '_';
-
- if (*--p == '.') /* zap trailing period */
- *p = 0;
- }
-
- if (!Zmodem && MakeLCPathname && !IsAnyLower(name))
- uncaps(name);
- if (Topipe)
- {
- #ifndef MSDOS
- sprintf(Pathname, "%s %s", Progname+2, name);
- if (Verbose)
- fprintf(stderr, "Topipe: %s %s\n",
- Pathname, Thisbinary ? "BIN" : "ASCII");
- if ((fout = popen(Pathname, "w")) == NULL)
- return(ERROR);
- #else
- if (Verbose)
- fprintf(stderr, "Topipe: stdout %s\n", Thisbinary ? "BIN" : "ASCII");
- fout = stdout;
- #endif
- }
- else
- {
- strcpy(Pathname, name);
- if (Verbose)
- fprintf(stderr, "Receiving %s %s %s\n",
- name, Thisbinary ? "BIN" : "ASCII", openmode);
- checkpath(name);
- if (Nflag)
- #ifndef MSDOS
- name = "/dev/null";
- #else
- name = "nul";
- #endif
- if ((fout = fopen(name, openmode)) == NULL)
- return(ERROR);
- }
- return(OK);
- }
-
- /*
- * Putsec writes the n characters of buf to receive file fout.
- * If not in binary mode, carriage returns, and all characters
- * starting with CPMEOF are discarded.
- */
- putsec(buf, n)
- char *buf;
- int n;
- {
- char *p;
-
- if (Thisbinary)
- for (p = buf; --n >= 0; )
- putc(*p++, fout);
- else
- {
- if (Eofseen)
- return(OK);
- for (p = buf; --n >= 0; ++p )
- {
- if (*p == '\r')
- continue;
- if (*p == CPMEOF)
- {
- Eofseen = TRUE;
- return(OK);
- }
- putc(*p++, fout);
- }
- }
- return(OK);
- }
-
- /*
- * Send a character to modem. Small is beautiful.
- */
- sendline(c)
- {
- char d;
-
- d = c;
- if (Verbose > 4)
- fprintf(stderr, "Sendline: %x\n", c);
- #ifndef MSDOS
- write(1, &d, 1);
- #else
- tty_write(iofd, &d, 1);
- #endif
- }
-
- xsendline(c)
- {
- sendline(c);
- }
-
- flushmo()
- {;}
-
-
-
-
- /* make string s lower case */
- uncaps(s)
- char *s;
- {
- for ( ; *s; ++s)
- if (isupper(*s))
- *s = tolower(*s);
- }
- /*
- * IsAnyLower returns TRUE if string s has lower case letters.
- */
- IsAnyLower(s)
- char *s;
- {
- for ( ; *s; ++s)
- if (islower(*s))
- return(TRUE);
- return(FALSE);
- }
-
- /*
- * substr(string, token) searches for token in string s
- * returns pointer to token within string if found, NULL otherwise
- */
- char *substr(s, t)
- char *s,*t;
- {
- char *ss,*tt;
- /* search for first char of token */
- for (ss = s; *s; s++)
- if (*s == *t)
- /* compare token with substring */
- for (ss = s,tt = t; ;)
- {
- if (*tt == 0)
- return(s);
- if (*ss++ != *tt++)
- break;
- }
- return(NULL);
- }
-
- /*
- * Log an error
- */
- /*VARARGS1*/
- log(s,p,u)
- char *s, *p, *u;
- {
- if (!Verbose)
- return;
- fprintf(stderr, "error %d: ", errors);
- fprintf(stderr, s, p, u);
- }
-
- /* send cancel string to get the other end to shut up */
- canit()
- {
- static char canistr[] =
- {
- 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
- };
- #ifndef MSDOS
- printf(canistr);
- #else
- tty_write(iofd, canistr, strlen(canistr));
- #endif
- Lleft = 0; /* Do read next time ... */
- fflush(stdout);
- }
-
-
- /*
- * Return 1 iff stdout and stderr are different devices
- * indicating this program operating with a modem on a
- * different line
- */
- fromcu()
- {
- #ifndef MSDOS
- struct stat a, b;
- fstat(1, &a);
- fstat(2, &b);
- return(a.st_rdev != b.st_rdev);
- #else
- return(1);
- #endif
- }
-
- report(sct)
- int sct;
- {
- if (Verbose > 1)
- fprintf(stderr,"%03d%c",sct,sct%10? ' ' : '\r');
- }
-
- /*
- * If called as [-][dir/../]vrzCOMMAND set Verbose to 1
- * If called as [-][dir/../]rzCOMMAND set the pipe flag
- * If called as rb use YMODEM protocol
- */
- chkinvok(s)
- char *s;
- {
- char *p;
-
- p = s;
- while (*p == '-')
- s = ++p;
- while (*p)
- if (*p++ == '/')
- s = p;
- if (*s == 'v')
- {
- Verbose = 1;
- ++s;
- }
- Progname = s;
- if (s[0] == 'r' && s[1] == 'b')
- Nozmodem = TRUE;
- if (s[2] && s[0] == 'r' && s[1] == 'b')
- Topipe = TRUE;
- if (s[2] && s[0] == 'r' && s[1] == 'z')
- Topipe = TRUE;
- }
-
- /*
- * Totalitarian Communist pathname processing
- */
- checkpath(name)
- char *name;
- {
- if (Restricted)
- {
- if (fopen(name, "r") != NULL)
- {
- canit();
- fprintf(stderr, "\r\nrz: %s exists\n", name);
- bibi();
- }
- /* restrict pathnames to current tree or uucppublic */
- if (substr(name, "../")
- || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) )
- {
- canit();
- fprintf(stderr,"\r\nrz:\tSecurity Violation\r\n");
- bibi();
- }
- }
- }
-
- /*
- * Initialize for Zmodem receive attempt, try to activate Zmodem sender
- * Handles ZSINIT frame
- * Return ZFILE if Zmodem filename received, -1 on error,
- * ZCOMPL if transaction finished, else 0
- */
- tryz()
- {
- int c, n;
- int cmdzack1flg;
-
- if (Nozmodem) /* Check for "rb" program name */
- return(0);
-
-
- for (n = Zmodem ? 10 : 5; --n >= 0; )
- {
- /* Set buffer length (0) and capability flags */
- stohdr(0L);
- #ifdef CANBREAK
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
- #else
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
- #endif
- zshhdr(tryzhdrtype, Txhdr);
- again:
- switch (zgethdr(Rxhdr, 0))
- {
- case ZRQINIT:
- continue;
- case ZEOF:
- continue;
- case TIMEOUT:
- continue;
- case ZFILE:
- zconv = Rxhdr[ZF0];
- zmanag = Rxhdr[ZF1];
- ztrans = Rxhdr[ZF2];
- tryzhdrtype = ZRINIT;
- if (zrdata(secbuf, KSIZE) == GOTCRCW)
- return(ZFILE);
- zshhdr(ZNAK, Txhdr);
- goto again;
- case ZSINIT:
- if (zrdata(Attn, ZATTNLEN) == GOTCRCW)
- {
- zshhdr(ZACK, Txhdr);
- goto again;
- }
- zshhdr(ZNAK, Txhdr);
- goto again;
- case ZFREECNT:
- stohdr(getfree());
- zshhdr(ZACK, Txhdr);
- goto again;
- case ZCOMMAND:
- cmdzack1flg = Rxhdr[ZF0];
- if (zrdata(secbuf, KSIZE) == GOTCRCW)
- {
- if (cmdzack1flg & ZCACK1)
- stohdr(0L);
- else
- stohdr((long)sys2(secbuf));
- purgeline(); /* dump impatient questions */
- do
- zshhdr(ZCOMPL, Txhdr);
- while (++errors < 10 && zgethdr(Rxhdr, 1) != ZFIN);
- ackbibi();
- if (cmdzack1flg & ZCACK1)
- exec2(secbuf);
- return(ZCOMPL);
- }
- zshhdr(ZNAK, Txhdr);
- goto again;
- case ZCOMPL:
- goto again;
- default:
- continue;
- case ZFIN:
- ackbibi();
- return(ZCOMPL);
- case ZCAN:
- return(ERROR);
- }
- }
- return(0);
- }
-
- /*
- * Receive 1 or more files with ZMODEM protocol
- */
- rzfiles()
- {
- int c;
-
- for (;;)
- {
- switch (c = rzfile())
- {
- case ZEOF:
- case ZSKIP:
- switch (tryz())
- {
- case ZCOMPL:
- return(OK);
- default:
- return(ERROR);
- case ZFILE:
- break;
- }
- continue;
- default:
- return(c);
- case ERROR:
- return(ERROR);
- }
- }
- }
-
- /*
- * Receive a file with ZMODEM protocol
- * Assumes file name frame is in secbuf
- */
- rzfile()
- {
- int c, n;
- long rxbytes;
-
- Eofseen = FALSE;
- if (procheader(secbuf) == ERROR)
- return((tryzhdrtype = ZSKIP));
-
- n = 10;
- rxbytes = 0l;
-
- for (;;)
- {
- stohdr(rxbytes);
- zshhdr(ZRPOS, Txhdr);
- nxthdr:
- switch (c = zgethdr(Rxhdr, 0))
- {
- default:
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- case ZNAK:
- case TIMEOUT:
- if ( --n < 0)
- {
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- }
- case ZFILE:
- zrdata(secbuf, KSIZE);
- continue;
- case ZEOF:
- if (rclhdr(Rxhdr) != rxbytes)
- continue;
- if (closeit())
- {
- tryzhdrtype = ZFERR;
- vfile("rzfile: closeit returned <> 0");
- return(ERROR);
- }
- vfile("rzfile: normal EOF");
- return(c);
- case ERROR: /* Too much garbage in header search error */
- if (--n < 0)
- {
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- }
- zmputs(Attn);
- continue;
- case ZDATA:
- if (rclhdr(Rxhdr) != rxbytes)
- {
- if (--n < 0)
- return(ERROR);
- zmputs(Attn); continue;
- }
- moredata:
- switch (c = zrdata(secbuf, KSIZE))
- {
- case ZCAN:
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- case ERROR: /* CRC error */
- if (--n < 0)
- {
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- }
- zmputs(Attn);
- continue;
- case TIMEOUT:
- if (--n < 0)
- {
- vfile("rzfile: zgethdr returned %d", c);
- return(ERROR);
- }
- continue;
- case GOTCRCW:
- n = 10;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(ZACK, Txhdr);
- goto nxthdr;
- case GOTCRCQ:
- n = 10;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(ZACK, Txhdr);
- goto moredata;
- case GOTCRCG:
- n = 10;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- goto moredata;
- case GOTCRCE:
- n = 10;
- putsec(secbuf, Rxcount);
- rxbytes += Rxcount;
- goto nxthdr;
- }
- }
- }
- }
-
- /*
- * Send a string to the modem, processing for \336 (sleep 1 sec)
- * and \335 (break signal)
- */
- zmputs(s)
- char *s;
- {
- int c;
-
- while (*s)
- {
- switch (c = *s++)
- {
- case '\336':
- sleep(1);
- continue;
- case '\335':
- sendbrk();
- continue;
- default:
- sendline(c);
- }
- }
- }
-
- /*
- * Close the receive dataset, return OK or ERROR
- */
- closeit()
- {
- if (Topipe)
- {
- #ifndef MSDOS
- if (pclose(fout))
- return(ERROR);
- #endif
- return(OK);
- }
- if (fclose(fout) == ERROR)
- {
- fprintf(stderr, "file close ERROR\n");
- return(ERROR);
- }
- if (Modtime)
- {
- timep[0] = time(NULL);
- #ifndef MSDOS
- timep[1] = Modtime;
- #else
- timep[1] = Modtime - JAN1ST70;
- #endif
- utime(Pathname, timep);
- }
- if (Filemode)
- chmod(Pathname, (07777 & Filemode));
- return(OK);
- }
-
- /*
- * Ack a ZFIN packet, let byegones be byegones
- */
- ackbibi()
- {
- int n;
-
- vfile("ackbibi:");
- Readnum = 1;
- stohdr(0L);
- for (n = 4; --n>=0; )
- {
- zshhdr(ZFIN, Txhdr);
- for (;;)
- {
- switch (readline(100))
- {
- case 'O':
- readline(1); /* Discard 2nd 'O' */
- /* ***** FALL THRU TO ***** */
- case TIMEOUT:
- vfile("ackbibi complete");
- return;
- default:
- break;
- }
- }
- }
- }
-
- /*
- * Local console output simulation
- */
- bttyout(c)
- {
- if (Verbose || fromcu())
- putc(c, stderr);
- }
-
- /*
- * Strip leading ! if present, do shell escape.
- */
- sys2(s)
- char *s;
- {
- if (*s == '!')
- ++s;
- return(system(s));
- }
- /*
- * Strip leading ! if present, do exec.
- */
- exec2(s)
- char *s;
- {
- if (*s == '!')
- ++s;
- mode(0);
- execl("/bin/sh", "sh", "-c", s);
- }